package msearch.mp3;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import msearch.utils.Mp3Analysizer;


public class MP3 {
private static Map<Integer,String> style=new HashMap<Integer,String>();

public MP3.SongInfo songInfo;
public MP3.SongInfo getSongInfo() {
	return songInfo;
}
public void setSongInfo(MP3.SongInfo songInfo) {
	this.songInfo = songInfo;
}
private MP3.DataInfo dataInfo;

private List<FrameData> frameList;
public MP3(String filename) throws Exception{
File file=new File(filename);
byte[] bufLast=new byte[128];//锟斤拷尾128锟街斤拷
byte[] bufFront=new byte[10];//锟斤拷头10锟街斤拷
byte[] bufFrame=null;//锟叫硷拷锟斤拷锟街�
byte[] headLabel=null;//锟斤拷签帧(未知锟斤拷锟饺猴拷帧锟斤拷)
try {
FileInputStream is=new FileInputStream(file);
try {
is.read(bufFront,0,10);
this.dataInfo=new MP3.DataInfo(bufFront);

headLabel=new byte[this.dataInfo.getSize()];
is.read(headLabel, 0, headLabel.length);
this.ID3ByHeadList(headLabel);

bufFrame=new byte[(int) (file.length()-128-10-headLabel.length)];
is.read(bufFrame, 0, bufFrame.length);
//this.analyseFrame(bufFrame);

is.skip(file.length()-(128+10+headLabel.length+bufFrame.length));
is.read(bufLast, 0, 128);
this.songInfo=new MP3.SongInfo(bufLast);



} catch (IOException e) {
System.out.println("锟侥硷拷锟斤拷取锟斤拷锟斤拷"+file.getAbsolutePath()+" 锟侥硷拷锟斤拷锟饺诧拷锟斤拷128锟斤拷");
e.printStackTrace();
}
} catch (FileNotFoundException e) {
System.out.println("锟侥硷拷路锟斤拷锟斤拷"+file.getAbsolutePath()+" 锟斤拷锟斤拷锟节★拷");
//e.printStackTrace();
}
}
static{
/*Standard genre*/
style.put(0,"Blues");
style.put(1,"ClassicRock");
style.put(2,"Country");
style.put(3,"Dance");
style.put(4,"Disco");
style.put(5,"Funk");
style.put(6,"Grunge");
style.put(7,"Hip-Hop");
style.put(8,"Jazz");
style.put(9,"Metal");
style.put(10,"NewAge");
style.put(11,"Oldies");
style.put(12,"Other");
style.put(13,"Pop");
style.put(14,"R&B");
style.put(15,"Rap");
style.put(16,"Reggae");
style.put(17,"Rock");
style.put(18,"Techno");
style.put(19,"Industrial");
style.put(20,"Alternative");
style.put(21,"Ska");
style.put(22,"DeathMetal");
style.put(23,"Pranks");
style.put(24,"Soundtrack");
style.put(25,"Euro-Techno");
style.put(26,"Ambient");
style.put(27,"Trip-Hop");
style.put(28,"Vocal");
style.put(29,"Jazz+Funk");
style.put(30,"Fusion");
style.put(31,"Trance");
style.put(32,"Classical");
style.put(33,"Instrumental");
style.put(34,"Acid");
style.put(35,"House");
style.put(36,"Game");
style.put(37,"SoundClip");
style.put(38,"Gospel");
style.put(39,"Noise");
style.put(40,"AlternRock");
style.put(41,"Bass");
style.put(42,"Soul");
style.put(43,"Punk");
style.put(44,"Space");
style.put(45,"Meditative");
style.put(46,"InstrumentalPop");
style.put(47,"InstrumentalRock");
style.put(48,"Ethnic");
style.put(49,"Gothic");
style.put(50,"Darkwave");
style.put(51,"Techno-Industrial");
style.put(52,"Electronic");
style.put(53,"Pop-Folk");
style.put(54,"Eurodance");
style.put(55,"Dream");
style.put(56,"SouthernRock");
style.put(57,"Comedy");
style.put(58,"Cult");
style.put(59,"Gangsta");
style.put(60,"Top40");
style.put(61,"ChristianRap");
style.put(62,"Pop/Funk");
style.put(63,"Jungle");
style.put(64,"NativeAmerican");
style.put(65,"Cabaret");
style.put(66,"NewWave");
style.put(67,"Psychadelic");
style.put(68,"Rave");
style.put(69,"Showtunes");
style.put(70,"Trailer");
style.put(71,"Lo-Fi");
style.put(72,"Tribal");
style.put(73,"AcidPunk");
style.put(74,"AcidJazz");
style.put(75,"Polka");
style.put(76,"Retro");
style.put(77,"Musical");
style.put(78,"Rock&Roll");
style.put(79,"HardRock");
/*Extended genre*/
style.put(80,"Folk");
style.put(81,"Folk-Rock");
style.put(82,"NationalFolk");
style.put(83,"Swing");
style.put(84,"FastFusion");
style.put(85,"Bebob");
style.put(86,"Latin");
style.put(87,"Revival");
style.put(88,"Celtic");
style.put(89,"Bluegrass");
style.put(90,"Avantgarde");
style.put(91,"GothicRock");
style.put(92,"ProgessiveRock");
style.put(93,"PsychedelicRock");
style.put(94,"SymphonicRock");
style.put(95,"SlowRock");
style.put(96,"BigBand");
style.put(97,"Chorus");
style.put(98,"EasyListening");
style.put(99,"Acoustic");
style.put(100,"Humour");
style.put(101,"Speech");
style.put(102,"Chanson");
style.put(103,"Opera");
style.put(104,"ChamberMusic");
style.put(105,"Sonata");
style.put(106,"Symphony");
style.put(107,"BootyBass");
style.put(108,"Primus");
style.put(109,"PornGroove");
style.put(110,"Satire");
style.put(111,"SlowJam");
style.put(112,"Club");
style.put(113,"Tango");
style.put(114,"Samba");
style.put(115,"Folklore");
style.put(116,"Ballad");
style.put(117,"PowerBallad");
style.put(118,"RhythmicSoul");
style.put(119,"Freestyle");
style.put(120,"Duet");
style.put(121,"PunkRock");
style.put(122,"DrumSolo");
style.put(123,"Acapella");
style.put(124,"Euro-House");
style.put(125,"DanceHall");
style.put(126,"Goa");
style.put(127,"Drum&Bass");
style.put(128,"Club-House");
style.put(129,"Hardcore");
style.put(130,"Terror");
style.put(131,"Indie");
style.put(132,"BritPop");
style.put(133,"Negerpunk");
style.put(134,"PolskPunk");
style.put(135,"Beat");
style.put(136,"ChristianGangstaRap");
style.put(137,"HeavyMetal");
style.put(138,"BlackMetal");
style.put(139,"Crossover");
style.put(140,"ContemporaryChristian");
style.put(141,"ChristianRock");
style.put(142,"Merengue");
style.put(143,"Salsa");
style.put(144,"TrashMetal");
style.put(145,"Anime");
style.put(146,"JPop");
style.put(147,"Synthpop");
}
class DataInfo implements PrivateInfo{
/*
char Header[3];  锟街凤拷 "ID3" 

char Ver;        锟芥本锟斤拷ID3V2.3 锟酵硷拷录3 

char Revision;  锟斤拷锟芥本锟脚此版本锟斤拷录为0 

char Flag;      锟斤拷疟锟街撅拷锟斤拷纸冢锟斤拷锟斤拷锟芥本只锟斤拷锟斤拷锟斤拷锟斤拷位锟斤拷锟斤拷锟斤拷锟矫碉拷锟斤拷锟斤拷锟皆猴拷锟斤拷 

char Size[4];  锟斤拷签锟斤拷小锟斤拷锟斤拷锟剿憋拷签头锟斤拷10 锟斤拷锟街节的憋拷签帧锟侥达拷小 


*/
private String id3;
private String ver;
private String revision;
private String flag;
private int size;


public DataInfo(byte[] data) throws Exception{
byte[] temp=null;
if(data.length!=10) {
System.out.println("锟斤拷莶锟斤拷锟�0锟街节伙拷锟竭达拷锟斤拷10锟街节ｏ拷");
throw new Exception();
}
int pos=0;
temp=new byte[3];
System.arraycopy(data,pos,temp,0,3);
this.id3=new String(temp);
pos=pos+temp.length;

temp=new byte[1];
System.arraycopy(data,pos,temp,0,1);
this.ver=new String(temp);
pos=pos+temp.length;

temp=new byte[1];
System.arraycopy(data,pos,temp,0,1);
this.revision=new String(temp);
pos=pos+temp.length;

temp=new byte[1];
System.arraycopy(data,pos,temp,0,1);
this.flag=new String(temp);
pos=pos+temp.length;

temp=new byte[4];
System.arraycopy(data,pos,temp,0,4);
this.size=MP3.getSizeByByte(temp);

}
public int getSize(){
return this.size;
}
}
class SongInfo implements PublicInfo{
private String tag;

private String title;
private String artist;
private String album;
private String year;
private String comment;
private String genre;

private String reserve;
private String track;

public SongInfo(byte[] data) throws Exception{
byte[] temp=null;
if(data.length!=128){
System.out.println("锟斤拷莶锟斤拷锟�28锟街节伙拷锟竭达拷锟斤拷128锟街节ｏ拷");
throw new Exception();
}
int pos=0;
temp=new byte[3];
System.arraycopy(data,pos,temp,0,3);
this.tag=new String(temp);
pos=pos+temp.length;

if(!this.tag.equals("TAG")){
return;
}

temp=new byte[30];
System.arraycopy(data, pos, temp, 0, 30);
this.title=new String(temp);
pos=pos+temp.length;

temp=new byte[30];
System.arraycopy(data, pos, temp, 0, 30);
this.artist=new String(temp);
pos=pos+temp.length;

temp=new byte[30];
System.arraycopy(data, pos, temp, 0, 30);
this.album=new String(temp);
pos=pos+temp.length;

temp=new byte[4];
System.arraycopy(data, pos, temp, 0, 4);
this.year=new String(temp);
pos=pos+temp.length;

temp=new byte[28];
System.arraycopy(data, pos, temp, 0, 28);
this.comment=new String(temp);
pos=pos+temp.length;

temp=new byte[1];
System.arraycopy(data, pos, temp, 0, 1);
this.reserve=new String(temp);
pos=pos+temp.length;

temp=new byte[1];
System.arraycopy(data, pos, temp, 0, 1);
this.track=new String(temp);
pos=pos+temp.length;

temp=new byte[1];
System.arraycopy(data, pos, temp, 0, 1);
this.genre=style.get(new Byte(temp[0]).intValue());

}

public String getAlbum() {
// TODO 锟皆讹拷锟斤拷煞锟斤拷锟斤拷锟斤拷
return this.album;
}

public String getArtist() {
// TODO 锟皆讹拷锟斤拷煞锟斤拷锟斤拷锟斤拷
return this.artist;
}

public String getComment() {
// TODO 锟皆讹拷锟斤拷煞锟斤拷锟斤拷锟斤拷
return this.comment;
}

public String getGenre() {
// TODO 锟皆讹拷锟斤拷煞锟斤拷锟斤拷锟斤拷
return this.genre;
}

public String getTitle() {
// TODO 锟皆讹拷锟斤拷煞锟斤拷锟斤拷锟斤拷
return this.title;
}

public String getYaer() {
// TODO 锟皆讹拷锟斤拷煞锟斤拷锟斤拷锟斤拷
return this.year;
}

}
private static int getSizeByByte(byte[] temp){
//return   (int)(temp[0] & 0x7F) << 21| (int)(temp[1] & 0x7F) << 14| (int)(temp[2] & 0x7F) << 7| (int)(temp[3] & 0x7F) + 10;
int r=1;
if(temp[0]+temp[1]+temp[2]+temp[3]==0) return 0;
for(int x=0;x<4;x++)
if(temp[x]!=0) r=r*temp[x];
return r;
}
private Map<String,String> ID3ByHeadList(byte[] buf){
/*
* 锟斤拷签帧锟斤拷 | 锟斤拷锟斤拷锟�| 锟斤拷莩锟斤拷锟�| 锟斤拷锟�| [锟斤拷实锟斤拷锟絔 | .....
*/
Map<String,String> map=new HashMap<String,String>();
int pix=0;
byte[] head;//4
byte[] size;//4
byte[] flag;//2
int dataLeng=0;
byte[] dataBuf;//n

for(;pix<buf.length;){
head=new byte[4];
size=new byte[4];
flag=new byte[2];
System.arraycopy(buf, pix, head, 0, 4);
pix=pix+4;
System.arraycopy(buf, pix, size, 0, 4);
pix=pix+4;
System.arraycopy(buf, pix, flag, 0, 2);
pix=pix+2;
dataLeng=getSizeByByte(size);
if(dataLeng<=0) return map;
//System.out.println(dataLeng);
dataBuf=new byte[dataLeng];
System.arraycopy(buf, pix, dataBuf, 0, dataLeng);
pix=pix+dataLeng;
map.put(new String(head), new String(dataBuf));
//System.out.println(new String(head)+" \t| "+new String(dataBuf)+" \t| "+pix);

}


return map;

}
private void analyseFrame(byte[] frameByte) throws Exception{
frameList=new LinkedList<FrameData>();
int pix=0;
int size=0;
byte[] frameHead;//帧头
byte[] frameData;//锟斤拷锟街�
for(;pix<frameByte.length;){
frameHead=new byte[4];
System.arraycopy(frameByte, pix, frameHead, 0, 4);
pix=pix+4;
if(pix>=frameByte.length) break;

FrameData frame=new FrameData(frameHead);
size=frame.getBitSize();
if(size<=0) continue;
//if(size<0) break;//锟角凤拷注锟斤拷
frameData=new byte[size];
System.out.println("SIZE:"+size+"  锟斤拷取源锟斤拷锟介开始位锟斤拷:"+pix+"  锟斤拷锟斤拷锟斤拷锟叫�"+frameData.length+"  锟斤拷锟饺ｏ拷 "+frame.getBitSize()+"  锟杰达拷小锟斤拷"+frameByte.length);
System.arraycopy(frameByte, pix, frameData, 0, frame.getBitSize());
pix=pix+frame.getBitSize();
System.out.println("PIX:"+pix+"   SIZE:"+size);
if(pix>=frameByte.length) break;
frame.setBitData(frameData);
this.frameList.add(frame);

//if (pix>500) break;

}
}
static public void main(String[] str) throws Exception{
MP3 mp3=new MP3("C:\\1.mp3");
System.out.println(mp3.songInfo.getTitle());
System.out.println(mp3.songInfo.getGenre());
System.out.println(mp3.dataInfo.getSize());
System.out.println(mp3.songInfo.getArtist());
System.out.println(mp3.songInfo.getAlbum());
System.out.println(mp3.songInfo.getYaer());
Mp3Analysizer.saveToDataBase("C:\\1.mp3");
}
public String getTitle(){
	return songInfo.getTitle();
}

public String getArtist(){
	return songInfo.getArtist();
}

public String getAlbum(){
	return songInfo.getAlbum();
}
public String getPublishDate(){
	return songInfo.getYaer();
}
}
